<?php
declare (strict_types = 1);

namespace app\api\controller;

use app\BaseController;
use app\model\Shops;
use app\model\Users;
use app\model\ChargeRecord;
use app\model\UrlRedirect;
use pay\ShanDeDirect;
use pay\EncryptHelp;
use think\exception\ValidateException;
use think\facade\Log;
use think\facade\Db;
use Ramsey\Uuid\Uuid;
use think\facade\Queue;

/**
 * 支付控制器
 */
class PaymentController extends BaseController
{
    /**
     * 查询会员状态
     * @param [type] $user_id   会员编号
     * @return object
     */
    private function getUserInfo($shop, $user_id)
    {
        // 查询是否存在该会员信息
        $user = Users::where("user_id", $user_id)->findOrEmpty();
        // 没有用户信息，查询用户信息
        if($user->isEmpty()){
            // 获取杉德直连对象
            $payments = $shop->payments()->where(["method_id"=> '1', "status"=> true, "channel_id"=> 1])->select()->toArray()[0];
            $pay_obj = new ShanDeDirect($payments["appid"], $payments["private_key"], $payments["public_key"], $payments["settle_secret"]);
            // 查询会员状态
            $data = $pay_obj->findNumberInfo($user_id);
            if($data['code'] != 0){
                return false;
            }
            $body = $data['data'];
            // 添加用户
            $user = Users::create(["shop_id"=> $shop->id, "user_id"=>$user_id, "card_name"=> $body["name"], "card_no"=> $body["idNo"], 'phone'=> $body["phone"], 
                "status"=> $body["open"], "open_status"=> $body["open"], "open_time"=> date("Y-m-d H:i:s")]);
        }
        return $user;
    }

    /**
     * 调起支付
     *
     * @return \think\Response
     */
    public function pay()
    {
        try{
            // 获取请求参数
            $request_data = request()->post();
            if(
                empty($request_data['app_code']) 
                || empty($request_data['amount']) 
                || empty($request_data['pay_type']) 
                || empty($request_data['user_id']) 
                || empty($request_data['order_no']) 
                || empty($request_data['cardName']) 
                || empty($request_data['cardNo']) 
                || empty($request_data['phone']) 
                || empty($request_data['ip']) 
                || empty($request_data['goods_name'])
            ){
                return common_out([], "参数有误！", 202);
            }

            // 查询是否存在商户号
            $shop = Shops::where('shop_code', $request_data['app_code'])->findOrEmpty();
            if ($shop->isEmpty()){
                return common_out([], "商户号不存在", 404);
            }

            // 状态判定、支付方式判定
            if($shop->shop_status == 0){
                return common_out([], "商户号状态异常", 400);
            }

            // 查询是否存在该会员信息
            $user_id = $shop->shop_name."-".$request_data["user_id"];
            $user = $this->getUserInfo($shop, $user_id);
            $is_register = false ? !$user : true;

            // 调起支付
            $payments = $shop->payments()->where(["method_id"=> '1', "status"=> true])->select()->toArray()[0];

            // 调起杉德支付
            $pay_obj = new ShanDeDirect($payments["appid"], $payments["private_key"], $payments["public_key"], $payments["settle_secret"]);
            // 昵称
            $nickname = sprintf("%s|%s|%s|%s", $shop->shop_name."-".$request_data["cardName"], $request_data["cardName"], $request_data["cardNo"], $request_data["phone"]);
            // 用户标识
            $user_id = $shop->shop_name."-".$request_data["user_id"];
            $data = $pay_obj->pay($request_data["order_no"], $request_data["amount"], $request_data["ip"], $request_data["goods_name"], $user_id, $nickname, $is_register, $payments["return_url"]);

            if ($data["code"] == 0){
                // 创建订单记录
                $record = ChargeRecord::create([
                    "payment_id"=> $payments["id"],
                    "user_id"=> $user->id,
                    "amount"=> $request_data["amount"],
                    "pay_amount"=> $request_data["amount"],
                    "success_amount"=> $request_data["amount"],
                    "shop_order"=> $request_data["order_no"],
                    "platform_order"=> $request_data["order_no"],
                    "acquirer_order"=> $request_data["order_no"],
                    "describe"=> $request_data["goods_name"],
                    "ip"=> $request_data["ip"]
                ]);

                // 创建订单取消的队列消息
                Queue::push("app\api\job\ChargeJob@cancelOrder", ["id"=> $record->id]);
            }
            // 地址转换
            $req_id = str_replace('-', '', Uuid::uuid1()->toString());
            UrlRedirect::create(["url"=> $data["pay_url"], "req_id"=> $req_id]);

            return common_out(["url"=> sprintf("https://pay.gogoskins.com/api/shande?req_id=%s", $req_id)], $data["message"]);

        }catch(\Exception $e){
            return common_out("调起支付", $e, 500);
        }
    }

    /**
     * 查询订单接口
     *
     * @return void
     */
    public function findOrder()
    {
        try{
            // 获取请求参数
            $request_data = request()->get();
            if(empty($request_data['app_code']) || empty($request_data['order_sn']) || empty($request_data['pay_sn'])){
                return json(['code'=> 400, 'msg'=> '参数有误！']);
            }

            // 创建订单记录
            $record = ChargeRecord::where(["shop_order"=> $request_data["order_sn"], "platform_order"=> $request_data["pay_sn"]])->find();
            if(!$record){
                return common_out(["code"=> 404, "msg"=> "没定该订单信息"]);
            }

            // 查询订单状态
            $code = 1;
            if(!in_array($record->pay_status, [1, 2])) $code = 0;
            
            return common_out(["code"=> $code, "msg"=> "查询成功", "order_sn"=> $record->shop_order, "state"=> $record->pay_status, "pay_sn"=> $record->platform_order]);

        }catch(\Exception $e){
            return common_out("查询订单接口", $e, 500);
        }
    }

    /**
     * 重定向地址
     * @return void
     */
    public function shande()
    {
        try{
            // 获取请求参数
            $request_data = request()->get();
            if(empty($request_data['req_id'])){
                return json(['code'=> 400, 'msg'=> '参数有误！']);
            }

            // 查询是否有该链接
            $url = UrlRedirect::where(["req_id"=> $request_data['req_id']])->find();
            if(!$url){
                return json(['code'=> 400, 'msg'=> '地址有误!']);
            }

            // 重定向地址
            return redirect($url->url);

        }catch(\Exception $e){
            return json(['code'=> 500, 'msg'=> $e->getMessage(), 'line'=> $e->getLine()]);
        }
    }

    /**
     * 杉德钱包销户操作
     * @return void
     */
    public function cancel()
    {
        try{
            // 获取请求参数
            $request_data = request()->post();
            if(empty($request_data['user_id']) || empty($request_data['remark']) || empty($request_data['app_code'])){
                return json(['code'=> 400, 'msg'=> '参数有误！']);
            }

            // 查询是否存在商户号
            $shop = Shops::where('shop_code', $request_data['app_code'])->findOrEmpty();
            if ($shop->isEmpty()){
                return json(['code'=> 400, 'msg'=> '商户号不存在!']);
            }

            // 状态判定
            if($shop->shop_status == 0){
                return json(['code'=> 400, 'msg'=> '商户号状态异常!']);
            }

            // 查询是否存在该会员信息
            $user_id = $shop->shop_name."-".$request_data["user_id"];
            $user = Users::where("user_id", $user_id)->findOrEmpty();
            if($user->isEmpty()){
                return json(['code'=> 400, 'msg'=> '没有该用户信息!']);
            }

            // 获取杉德直连对象
            $payments = $shop->payments()->where(["method_id"=> '1', "status"=> true, "channel_id"=> 1])->select()->toArray()[0];
            $pay_obj = new ShanDeDirect($payments["appid"], $payments["private_key"], $payments["public_key"], $payments["settle_secret"]);
            // 销户操作
            $data = $pay_obj->NumberStatusManage($user_id, $payments["notify_url"], $payments["return_url"], $request_data['remark']);
            return json($data);

        }catch(\Exception $e){
            return json(['code'=> 500, 'msg'=> $e->getMessage()]);
        }
    }

    /**
     * 杉德钱包销户确认操作
     * @return void
     */
    public function cancelConfirm()
    {
        try{
            // 获取请求参数
            $request_data = request()->post();
            if(empty($request_data['user_id']) || empty($request_data['order_no']) || empty($request_data['code']) || empty($request_data['app_code'])){
                return json(['code'=> 400, 'msg'=> '参数有误！']);
            }

            // 查询是否存在商户号
            $shop = Shops::where('shop_code', $request_data['app_code'])->findOrEmpty();
            if ($shop->isEmpty()){
                return json(['code'=> 400, 'msg'=> '商户号不存在!']);
            }

            // 状态判定
            if($shop->shop_status == 0){
                return json(['code'=> 400, 'msg'=> '商户号状态异常!']);
            }

            // 查询是否存在该会员信息
            $user_id = $shop->shop_name."-".$request_data["user_id"];
            $user = Users::where("user_id", $user_id)->findOrEmpty();
            if($user->isEmpty()){
                return json(['code'=> 400, 'msg'=> '没有该用户信息!']);
            }

            // 获取杉德直连对象
            $payments = $shop->payments()->where(["method_id"=> '1', "status"=> true, "channel_id"=> 1])->select()->toArray()[0];
            $pay_obj = new ShanDeDirect($payments["appid"], $payments["private_key"], $payments["public_key"], $payments["settle_secret"]);
            // 销户确认操作
            $data = $pay_obj->NumberStatusManageConfirm($user_id, $request_data["order_no"], $request_data["code"]);
            return json($data);

        }catch(\Exception $e){
            return json(['code'=> 500, 'msg'=> $e->getMessage()]);
        }
    }

    /**
     * 支付回调
     *
     * @return void
     */
    public function payNotify()
    {
        $data = request()->post();
        // 记录日志
        Log::channel("api")->write(sprintf("支付回调: \n%s", var_export($data, true)));
        try{
            // 验证签名
            $verify = EncryptHelp::notify_verify($data["data"], $data["sign"]);
            if(!$verify){
                Log::channel("api")->write('支付回调签名失败');
            }
            $body = json_decode($data["data"], true)["body"];
            /** 返回参数
                * "mid" => "6888802124093"
                * "orderCode" => "1565564564654514"   商户订单号
                * "tradeNo" => "1565564564654514"  交易流水号
                * "sandSerialNo" => "231220112101141000133091"     // 杉德订单号
                * "clearDate" => "20231220"         交易日期
                * "totalAmount" => "000000000001"    订单金额
                * "orderStatus" => "1"   订单状态      1-成功
                * "payTime" => "20231220112225"    支付时间
                * "settleAmount" => "000000000001"   应结订单金额
                * "buyerPayAmount" => "000000000001"   买家付款金额
                * "discAmount" => "000000000000"  优惠金额
                * "txnCompleteTime" => "20231220112225"    通道支付时间
                * "payOrderCode" => "20231220sdb47910000010739"   渠道订单号
                * "accLogonNo" => "gogo-2"   付款人支付账号
                * "accNo" => "201115*****0007"   付款账号
                * "midFee" => "000000000000"   商户手续费
                * "extraFee" => "000000000000"     额外手续费
                * "specialFee" => "000000000000"   节假日手续费
                * "plMidFee" => "000000000000"     平台手续费
                * "bankserial" => ""   通道订单号
                * "externalProductCode" => "00002046"      产品编号
                * "cardNo" => "201115*****0007"        卡号
                * "creditFlag" => "2"      借贷记  1 借记卡 2 贷记卡
                * "bid" => ""      签约号
                * "benefitAmount" => "000000000000"   营销优惠金额
                * "remittanceCode" => ""  识别码
                * "extend" => ""  扩展域
                * "accountAmt" => "000000000001"  
                * "masterAccount" => "201115000050007" 
            */
            // 查询是否有该订单
            $order = Db::query("SELECT c.id, c.shop_order, c.platform_order, c.amount, c.pay_amount, c.order_status, c.pay_status, p.notify_url, pc.pay_code, u.user_id
                FROM charge_record as c 
                LEFT JOIN shop_payments as p ON c.payment_id = p.id
                LEFT JOIN payment_channels as pc ON pc.id = p.channel_id
                LEFT JOIN users as u ON u.id = c.user_id
                WHERE c.shop_order = ? AND c.order_status = 0 AND c.pay_status = 0
            ", [$body["orderCode"]]);
            if(!$order){
                throw new ValidateException("订单不存在");
            }
            if(count($order) > 1){
                throw new ValidateException("订单不唯一");
            }
            $order = $order[0];
            if($order["pay_code"] != "ShanDeDirect" || $order["user_id"] != $body["accLogonNo"]){
                throw new ValidateException("订单信息不对应!");
            }

            // 开启事务
            Db::startTrans();
            try {
                // 更新订单状态
                $update = [
                    "order_status"=> 1, 
                    "pay_status"=> true, 
                    "pay_amount"=> round($body["buyerPayAmount"] / 100, 2), 
                    "success_amount"=> round($body["buyerPayAmount"] / 100, 2),
                    "platform_order"=> $body["sandSerialNo"], "acquirer_order"=> $body["payOrderCode"], "update_time"=> date("Y-m-d H:i:s")
                ];
                $status = ChargeRecord::where(["id"=>$order["id"], "order_status"=> 0, "pay_status"=> 0])->save($update);
                if(!$status){
                    throw new \Exception();
                }
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                throw new ValidateException("更新订单状态失败!");
            }

            // 通知三方网站支付成功
            Queue::push("app\api\job\ChargeJob@noticePartiesWeb", ["id"=> $order["id"], "url"=> $order["notify_url"], "order_sn"=> $order["shop_order"],  
                "pay_order"=> $order["platform_order"], "status"=> 1, "msg"=> "支付成功", "amount"=> $order["amount"], "success_amount"=> $order["pay_amount"]]);

            die("success");
        }catch(ValidateException $v){
            Log::channel("api")->write(sprintf("支付回调失败: \n%s", $v->getMessage()));
        }catch(\Exception $e){
            Log::channel("api")->write(sprintf("支付回调异常: \n%s\n%s", $e->getMessage(), $e->getTraceAsString()));
        }
        die("fail");
    }

    /**
     * 用户回调
     *
     * @return void
     */
    public function userNotify()
    {
        // 记录日志
        Log::channel("api")->write(sprintf("用户回调: \n%s", var_export(request()->post(), true)));
        die("success");
    }

    /**
     * 查询会员状态
     *
     * @return void
     */
    public function findUserStatus()
    {
        try{
            // 获取请求参数
            $request_data = request()->get();
            if(empty($request_data['user_id']) || empty($request_data['app_code'])){
                return json(['code'=> 400, 'msg'=> '参数有误！']);
            }

            // 查询是否存在商户号
            $shop = Shops::where('shop_code', $request_data['app_code'])->findOrEmpty();
            if ($shop->isEmpty()){
                return json(['code'=> 400, 'msg'=> '商户号不存在!']);
            }

            // 状态判定
            if($shop->shop_status == 0){
                return json(['code'=> 400, 'msg'=> '商户号状态异常!']);
            }

            // 查询是否存在该会员信息
            $user_id = $shop->shop_name."-".$request_data["user_id"];
            $user = $this->getUserInfo($shop, $user_id);
            if(!$user){
                return json(['code'=> 400, 'msg'=> '没有该用户信息!']);
            }

            // 获取杉德直连对象
            $payments = $shop->payments()->where(["method_id"=> '1', "status"=> true, "channel_id"=> 1])->select()->toArray()[0];
            $pay_obj = new ShanDeDirect($payments["appid"], $payments["private_key"], $payments["public_key"], $payments["settle_secret"]);
            // 查询会员状态
            $data = $pay_obj->findNumberStatus($user_id);
            return json($data);
        }catch(\Exception $e){
            return json(['code'=> 500, 'msg'=> $e->getMessage()]);
        }
    }
}